1   /*
2    * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  /*
24   * @test
25   * @bug 4904082 4917089 6337226
26   * @summary Tests that integral division and related methods return the proper result and scale.
27   * @author Joseph D. Darcy
28   */
29  import java.math.*;
30  public class IntegralDivisionTests {
31  
32      static int dividetoIntegralValueTests() {
33          int failures = 0;
34  
35          // Exact integer quotient should have the same results from
36          // the exact divide and dividetoIntegralValue
37  
38  
39          // Rounded results
40          BigDecimal [][] moreTestCases = {
41              {new BigDecimal("11003"),   new BigDecimal("10"),   new BigDecimal("1100")},
42              {new BigDecimal("11003"),   new BigDecimal("1e1"),  new BigDecimal("1100.0")},
43              {new BigDecimal("1e9"),     new BigDecimal("1"),    new BigDecimal("1e9")},
44              {new BigDecimal("1e9"),     new BigDecimal("1.00"), new BigDecimal("1e9")},
45              {new BigDecimal("1e9"),     new BigDecimal("0.1"),  new BigDecimal("1e10")},
46              {new BigDecimal("10e8"),    new BigDecimal("0.1"),  new BigDecimal("10e9")},
47              {new BigDecimal("400e1"),   new BigDecimal("5"),    new BigDecimal("80e1")},
48              {new BigDecimal("400e1"),   new BigDecimal("4.999999999"),  new BigDecimal("8e2")},
49              {new BigDecimal("40e2"),    new BigDecimal("5"),    new BigDecimal("8e2")},
50          };
51  
52          for(BigDecimal [] testCase: moreTestCases) {
53              BigDecimal quotient;
54              if (! (quotient=testCase[0].divideToIntegralValue(testCase[1])).equals(testCase[2]) ){
55                  failures++;
56                  // BigDecimal exact = testCase[0].divide(testCase[1]);
57                  System.err.println();
58                  System.err.println("dividend  = " + testCase[0] + " scale = " + testCase[0].scale());
59                  System.err.println("divisor   = " + testCase[1] + " scale = " + testCase[1].scale());
60                  System.err.println("quotient  = " + quotient    + " scale = " + quotient.scale());
61                  System.err.println("expected  = " + testCase[2] + " scale = " + testCase[2].scale());
62                  // System.err.println("exact     = " + exact       + " scale = " + exact.scale());
63              }
64          }
65  
66          return failures;
67      }
68  
69      static int dividetoIntegralValueRoundedTests() {
70          int failures = 0;
71  
72          BigDecimal dividend = new BigDecimal("11003");
73          BigDecimal divisor = new BigDecimal("10");
74          BigDecimal [] quotients = {     // Expected results with precision =
75              new BigDecimal("1100"),     // 0
76              null,                       // 1
77              new BigDecimal("11e2"),     // 2
78              new BigDecimal("110e1"),    // 3
79              new BigDecimal("1100"),     // 4
80          };
81          failures += divideContextTestPrecs(dividend, divisor, quotients);
82  
83          dividend = new BigDecimal("11003");
84          divisor = new BigDecimal("1e1");
85          BigDecimal [] quotients2 = {    // Expected results with precision =
86              new BigDecimal("1100.0"),   // 0
87              null,                       // 1
88              new BigDecimal("11e2"),     // 2
89              new BigDecimal("110e1"),    // 3
90              new BigDecimal("1100"),     // 4
91              new BigDecimal("1100.0"),   // 5
92          };
93          failures += divideContextTestPrecs(dividend, divisor, quotients2);
94  
95          dividend = new BigDecimal("1230000");
96          divisor = new BigDecimal("100");
97          BigDecimal [] quotients3 = {    // Expected results with precision =
98              new BigDecimal("12300"),    // 0
99              null,                       // 1
100             null,                       // 2
101             new BigDecimal("123e2"),    // 3
102             new BigDecimal("1230e1"),   // 4
103             new BigDecimal("12300"),    // 5
104         };
105         failures += divideContextTestPrecs(dividend, divisor, quotients3);
106 
107         dividend = new BigDecimal("33");
108         divisor  = new BigDecimal("3");
109         BigDecimal [] quotients4 = {    // Expected results with precision =
110             new BigDecimal("11"),       // 0
111             null,                       // 1
112             new BigDecimal("11"),       // 2
113             new BigDecimal("11"),       // 3
114         };
115         failures += divideContextTestPrecs(dividend, divisor, quotients4);
116 
117         dividend = new BigDecimal("34");
118         divisor  = new BigDecimal("3");
119         BigDecimal [] quotients5 = {    // Expected results with precision =
120             new BigDecimal("11"),       // 0
121             null,                       // 1
122             new BigDecimal("11"),       // 2
123             new BigDecimal("11"),       // 3
124         };
125         failures += divideContextTestPrecs(dividend, divisor, quotients5);
126 
127         return failures;
128     }
129 
130     static int divideContextTestPrecs(BigDecimal dividend,
131                                       BigDecimal divisor,
132                                       BigDecimal[] quotients)
133     {
134         int failures = 0;
135         for(int i = 0; i < quotients.length; i++) {
136             BigDecimal result = null;
137             BigDecimal quotient = quotients[i];
138 
139             try {
140                 result = dividend.divideToIntegralValue(divisor,
141                                                         new MathContext(i, RoundingMode.DOWN));
142             } catch (ArithmeticException e) {
143                 if (quotient != null) {
144                     failures++;
145                     System.err.println();
146                     System.err.println("Unexpected exception:");
147                     System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
148                     System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
149                     System.err.println("expected  = " + quotient     + " scale = " + quotient.scale());
150                 }
151             }
152 
153             if (quotient != null) {
154                 if (! result.equals(quotient)) {
155                     failures++;
156                     System.err.println();
157                     System.err.println("Unexpected result:");
158                     System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
159                     System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
160                     System.err.println("quotient  = " + result       + " scale = " + result.scale());
161                     System.err.println("expected  = " + quotient     + " scale = " + quotient.scale());
162                     System.err.println("precision = " + i);
163                 }
164             } else {
165                 if (result != null) {
166                     failures++;
167                     System.err.println();
168                     System.err.println("Unexpected unexceptional result:");
169                     System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
170                     System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
171                     System.err.println("quotient  = " + result       + " scale = " + result.scale());
172                     System.err.println("precision = " + i);
173                 }
174             }
175 
176         }
177         return failures;
178     }
179 
180 
181     static int divideContextTests(BigDecimal dividend,
182                                   BigDecimal divisor,
183                                   BigDecimal expected,
184                                   MathContext mc) {
185         int failures = 0;
186 
187         failures += divideContextTest(dividend,              divisor,          expected,                mc);
188         failures += divideContextTest(dividend.negate(),     divisor.negate(), expected,                mc);
189 
190         if (expected != null) {
191             failures += divideContextTest(dividend.negate(), divisor,          expected.negate(),       mc);
192             failures += divideContextTest(dividend,          divisor.negate(), expected.negate(),       mc);
193         }
194 
195         return failures;
196     }
197 
198 
199     static int divideContextTest(BigDecimal dividend,
200                                  BigDecimal divisor,
201                                  BigDecimal expected,
202                                  MathContext mc)
203     {
204         int failures = 0;
205 
206         BigDecimal result = null;
207 
208         try {
209             result = dividend.divideToIntegralValue(divisor, mc);
210         } catch (ArithmeticException e) {
211             if (expected != null) {
212                 failures++;
213                 System.err.println();
214                 System.err.println("Unexpected exception:");
215                 System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
216                 System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
217                 System.err.println("expected  = " + expected     + " scale = " + expected.scale());
218                 System.err.println("MathContext  = " + mc);
219             }
220         }
221 
222         if (expected != null) {
223             if (! result.equals(expected)) {
224                 failures++;
225                 System.err.println();
226                 System.err.println("Unexpected result:");
227                 System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
228                 System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
229                 System.err.println("expected  = " + expected     + " scale = " + expected.scale());
230                 System.err.println("result    = " + result       + " scale = " + result.scale());
231                 System.err.println("MathContext  = " + mc);
232             }
233         } else {
234             if (result != null) {
235                 failures++;
236                 System.err.println();
237                 System.err.println("Unexpected unexceptional result:");
238                 System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
239                 System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
240                 System.err.println("quotient  = " + result       + " scale = " + result.scale());
241                 System.err.println("MathConext = " + mc);
242                 }
243         }
244 
245         return failures;
246     }
247 
248     static int dividetoIntegralValueScalingTests() {
249         int failures = 0;
250 
251         BigDecimal dividend = new BigDecimal("123456789000");
252         BigDecimal divisor = BigDecimal.ONE;
253         BigDecimal expected = new BigDecimal("123456789e3");
254         MathContext mc = new MathContext(9,RoundingMode.DOWN);
255         failures += divideContextTests(dividend, divisor, expected, mc);
256 
257 
258         // 100/3 = 33 remainder 1
259         int [] precisions = {0, 2, 3, 4};
260         dividend = new BigDecimal(100);
261         divisor  = new BigDecimal(3);
262         expected = new BigDecimal(33);
263 
264         for(RoundingMode rm: RoundingMode.values())
265             for(int precision: precisions) {
266                 failures += divideContextTests(dividend, divisor, expected,
267                                                new MathContext(precision, rm));
268             }
269 
270         // 123000/10 = 12300 remainder 0
271         dividend = new BigDecimal(123000);
272         divisor  = new BigDecimal(10);
273         int[] precisions1 = {0, 1, 2, 3, 4, 5};
274         BigDecimal[] expected1 = {
275             new BigDecimal("12300"),
276             null,
277             null,
278             new BigDecimal("123e2"),
279             new BigDecimal("1230e1"),
280             new BigDecimal("12300"),
281         };
282 
283         for(RoundingMode rm: RoundingMode.values())
284             for(int i = 0; i < precisions1.length; i++) {
285                 failures += divideContextTests(dividend, divisor,
286                                                expected1[i],
287                                                new MathContext(precisions1[i], rm));
288             }
289 
290         // 123e3/10 = 123e2 remainder 0
291         dividend = new BigDecimal("123e3");
292         divisor  = new BigDecimal(10);
293         int[] precisions2 = {0, 1, 2, 3, 4, 5};
294         BigDecimal[] expected2 = {
295             new BigDecimal("123e2"),
296             null,
297             null,
298             new BigDecimal("123e2"),
299             new BigDecimal("123e2"),
300             new BigDecimal("123e2"),
301         };
302 
303         for(RoundingMode rm: RoundingMode.values())
304             for(int i = 0; i < precisions2.length; i++) {
305                 failures += divideContextTests(dividend, divisor,
306                                                expected2[i],
307                                                new MathContext(precisions2[i], rm));
308             }
309 
310 
311         // 123000/1e1 = 12300.0 remainder 0
312         dividend = new BigDecimal("123000");
313         divisor  = new BigDecimal("1e1");
314         int[] precisions3 = {0, 1, 2, 3, 4, 5, 6};
315         BigDecimal[] expected3 = {
316             new BigDecimal("12300.0"),
317             null,
318             null,
319             new BigDecimal("123e2"),
320             new BigDecimal("1230e1"),
321             new BigDecimal("12300"),
322             new BigDecimal("12300.0"),
323         };
324 
325         for(RoundingMode rm: RoundingMode.values())
326             for(int i = 0; i < precisions3.length; i++) {
327                 failures += divideContextTests(dividend, divisor,
328                                                expected3[i],
329                                                new MathContext(precisions3[i], rm));
330             }
331 
332 
333 
334         return failures;
335     }
336 
337     public static void main(String argv[]) {
338         int failures = 0;
339 
340         failures += dividetoIntegralValueTests();
341         failures += dividetoIntegralValueRoundedTests();
342         failures += dividetoIntegralValueScalingTests();
343 
344         if (failures > 0) {
345             System.err.println("Encountered " + failures +
346                                " failures while testing integral division.");
347             throw new RuntimeException();
348         }
349     }
350 }